﻿using System;
using System.IO;
using Microsoft.Win32;
using VSLangProj;
using VSLangProj80;

namespace AzurePlugin.Converter
{
    public class WorkerRoleProjectConverter
    {
        private readonly ProjectAdapter _projectAdapter;

        public WorkerRoleProjectConverter(ProjectAdapter projectAdapter)
        {
            _projectAdapter = projectAdapter;
        }

        public void Convert()
        {
            ConverterLogger.Instance.Info("converting " + _projectAdapter.Project.Name + " to worker role");

            ConverterLogger.Instance.Info("adding worker role flag to " + _projectAdapter.Project.Name);
            _projectAdapter.SetProperty(Constants.RoleTypePropertyName, Constants.WorkerRoleTypePropertyValue);

            var fwProfile = _projectAdapter.GetProperty("TargetFrameworkProfile");
            if (!string.IsNullOrEmpty(fwProfile) && fwProfile == "Client")
            {
                ConverterLogger.Instance.Info("switching from .net client profile to full for " + _projectAdapter.Project.Name);
                _projectAdapter.RemoveProperty("TargetFrameworkProfile");
            }

            var projectConfigurationManager = new ProjectConfigurationManagerAdapter(_projectAdapter.Project.ConfigurationManager);

            #region build config checks
            //if (!((object[]) projectWithGuid.Project.ConfigurationManager.SupportedPlatforms).Any(x => x.ToString() == "AnyCPU" || x.ToString() == "X64"))
            //{
            //throw new Exception("Project does not support build for AnyCPU");
            //}
            #endregion

            if (!projectConfigurationManager.ContainsPlatform("Any CPU"))
            {
                ConverterLogger.Instance.Info("adding Any CPU target platform to " + _projectAdapter.Project.Name);
                var configuration =
                    projectConfigurationManager.GetConfiguration(PlatformTarget.X64)
                    ??
                    projectConfigurationManager.GetConfiguration(PlatformTarget.x86);

                if (configuration == null)
                    throw new ArgumentException(string.Format("Project's {0} build configuration does not include any of the supported platform targets (AnyCPU, X64, x86)", _projectAdapter.Project.Name));

                projectConfigurationManager.AddPlaform("Any CPU", configuration.PlatformName);
            }

            ConverterLogger.Instance.Info("adding Azure-related references to " + _projectAdapter.Project.Name);
            var vsProject = _projectAdapter.Project.Object as VSProject;
            var azureSDKInstallDir = (string) Registry.GetValue(Constants.AzureSDKInstallPathRegKey, Constants.AzureSDKInstallPathRegValue, null);
            foreach (var assemblyString in Constants.AssembliesToReference)
            {
                var reference = (Reference3) vsProject.References.Add(Path.Combine(azureSDKInstallDir, "Ref", assemblyString));
                reference.SpecificVersion = false;
            }

            // todo: add tracing. Microsoft.VisualStudio.CloudService.Wizard.SystemDiagnosticsElementHelper
            //System.Configuration.Configuration configuration = System.Configuration.ConfigurationManager.OpenExeConfiguration();

            // todo: consider taking installed templates from the system
            string templateContent;
            string templateName;

            ConverterLogger.Instance.Info("adding Azure worker role entry point to " + _projectAdapter.Project.Name);
            var languageGuid = Guid.Parse(_projectAdapter.Project.CodeModel.Language);
            if (languageGuid == Constants.CSharpLanguageGuid)
            {
                templateContent = Resources.Templates.WorkerRoleCSharpTemplate;
                templateName = "WorkerRole.cs";
            }
            else if (languageGuid == Constants.VBLanguageGuid)
            {
                templateContent = Resources.Templates.WorkerRoleVBTemplate;
                templateName = "WorkerRole.vb";
            }
            else
            {
                throw new Exception("Unsupported project language: " + languageGuid);
            }

            var directoryInfo = Directory.CreateDirectory(Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()));
            var tempFileName = Path.Combine(directoryInfo.FullName, templateName);
            var content = templateContent
                .Replace("$safeprojectname$", _projectAdapter.Project.Name)
                .Replace("$projectname$", _projectAdapter.Project.Name);
            File.WriteAllText(tempFileName, content);

            // just for the test env. Safe to delete in prod
            var existingFile = Path.Combine(Path.GetDirectoryName(_projectAdapter.Project.FullName), templateName);
            if (File.Exists(existingFile))
            {
                File.Delete(existingFile);
            }

            _projectAdapter.Project.ProjectItems.AddFromTemplate(tempFileName, templateName);
        }
    }
}
